package inet.app.tuvi.util;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

import android.graphics.Bitmap;
import android.os.Environment;
import android.util.Log;

/**
 * The class provides some method used to create file or folder in SDCard
 * 
 */
public class FileManager {

	public static final File EXTERNAL_FOLDER = Environment
			.getExternalStorageDirectory();
	public static final File ROOT_FOLDER = Environment.getRootDirectory();
	public static final File DATA_FOLDER = Environment.getDataDirectory();
	public static final File CACHE_DOWNLOAD_FOLDER = Environment
			.getDownloadCacheDirectory();
	public static final String EXTERNAL_PATH = EXTERNAL_FOLDER.getPath();
	public static final String ASSETS_PATH = "file:///android_asset/";

	public static final int FILE_NOT_FOUND = 1;
	public static final int IO_EXCEPTION = 2;
	public static final int OK = 3;
	
	private static final String TAG = "FileManager";

	/**
	 * Delete file or directory
	 */
	public static void removeFolder(File fileOrDirectory) {
		try {
			if (fileOrDirectory.isDirectory()) {
				for (File file : fileOrDirectory.listFiles()) {
					removeFolder(file);
				}
			}

			fileOrDirectory.delete();
		} catch (Exception e) {
			Log.e(TAG, e.toString());
		}
	}

	/**
	 * Created a new folder in SD card
	 * 
	 * @param nameOfFolder
	 *            name of folder is created
	 * @return Return true if create folder successfully, otherwise return false
	 */
	public static boolean createNewFolder(String nameOfFolder) {
		File newfolder = new File(EXTERNAL_FOLDER, nameOfFolder);
		return newfolder.mkdirs();
	}

	/**
	 * Created a new folder in SD card
	 * 
	 * @param parentPath
	 *            the path of folder parent contains its
	 * @param nameOfFolder
	 *            name of folder is created
	 * @return Return true if create folder successfully, otherwise return false
	 */
	public static boolean createNewFolder(String parentPath, String nameOfFolder) {
		File newfolder = new File(parentPath, nameOfFolder);
		return newfolder.mkdirs();
	}

	/**
	 * Create a new file in SD card
	 * 
	 * @param pathOfFile
	 *            The path of file is created
	 * @return true if the file has been created, false if it already exists.
	 */
	public static boolean createNewFile(String pathOfFile) {
		File file = new File(pathOfFile);
		try {
			return file.createNewFile();
		} catch (IOException e) {
			Log.d(TAG, e.toString());
		}
		return false;
	}

	/**
	 * Create a new file using the specified directory and name in SD card
	 * 
	 * @param dir
	 *            : directory of specified folder
	 * @param nameOfFile
	 *            : name of file is created
	 * @return true if the file has been created, false if it already exists.
	 */
	public static boolean createNewFile(File dir, String nameOfFile) {
		File file = new File(dir, nameOfFile);
		try {
			return file.createNewFile();
		} catch (IOException e) {
		}
		return false;
	}

	/**
	 * 
	 * @param file
	 * @param text
	 */
	public static void write(File file, String text) {
		if (text == null) {
			return;
		}
		FileOutputStream outputStream = null;
		try {
			outputStream = new FileOutputStream(file);
			outputStream.write(text.getBytes());
			outputStream.flush();
			outputStream.close();
			Log.d(TAG, "write file success");
		} catch (FileNotFoundException e) {
			Log.e(TAG, e.toString());
		} catch (IOException e) {
			Log.e(TAG, e.toString());
		}
	}

	public static String read(String path) {
		FileInputStream stream = null;
		try {
			stream = new FileInputStream(new File(path));
			FileChannel fc = stream.getChannel();
			MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0,
					fc.size());
			/* Instead of using default, pass in a decoder. */
			return Charset.defaultCharset().decode(bb).toString();
		} catch (FileNotFoundException e) {
			Log.e(TAG, e.toString());
		} catch (IOException e) {
			Log.e(TAG, e.toString());
		} finally {
			try {
				stream.close();
			} catch (IOException e) {
				Log.e(TAG, e.toString());
			}
		}
		return null;
	}

	public static int zipFile(File fileToZip, File fileZip) {
		ZipOutputStream zipOutputStream = null;
		FileInputStream fileInputStream = null;

		try {
			fileInputStream = new FileInputStream(fileToZip.getPath());

			zipOutputStream = new ZipOutputStream(new FileOutputStream(fileZip));
			zipOutputStream.setLevel(Deflater.DEFAULT_COMPRESSION);
			zipOutputStream.putNextEntry(new ZipEntry(fileToZip.getName()));

			copyInputStream(fileInputStream, zipOutputStream);

			zipOutputStream.closeEntry();
			zipOutputStream.close();
			fileInputStream.close();

		} catch (FileNotFoundException e) {
			return FILE_NOT_FOUND;
		} catch (IOException e) {
			return IO_EXCEPTION;
		}
		return OK;
	}

	public static void unzipFile(String fileName) {
		FileInputStream fileInputStream = null;
		FileOutputStream fileOutputStream = null;
		try {
			ZipFile zipFile = new ZipFile(fileName);

			Enumeration<?> e = zipFile.entries();

			while (e.hasMoreElements()) {
				ZipEntry entry = (ZipEntry) e.nextElement();
				if (entry.isDirectory()) {
					createNewFile(entry.getName());
					continue;
				}

				fileInputStream = new FileInputStream(entry.getName());
				fileOutputStream = new FileOutputStream(zipFile.getName());
				copyInputStream(fileInputStream, fileOutputStream);
			}
			zipFile.close();
		} catch (IOException e) {
		}
	}

	public static void copyInputStream(InputStream in, OutputStream out)
			throws IOException {
		byte[] buffer = new byte[1024];
		int len;
		while ((len = in.read(buffer)) >= 0)
			out.write(buffer, 0, len);
		in.close();
		out.close();
	}
	
	/**
	 * Save bitmap to file
	 * @param bmp
	 * 			bitmap
	 * @param uriFile
	 * 			file is saved
	 * @return
	 */
	public static boolean saveBitmapToFile(Bitmap bmp, String uriFile) {
		try {
			ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
			bmp.compress(Bitmap.CompressFormat.PNG, 90, outputStream);
			
			File file = new File(uriFile);
			if(!file.createNewFile()) {
				return false;
			}
			FileOutputStream fileOutputStream = new FileOutputStream(file);
			fileOutputStream.write(outputStream.toByteArray());
			fileOutputStream.close();
			
			return true;
		} catch (FileNotFoundException e) {
			Log.e(TAG, e.toString());
			return false;
		} catch(IOException e) {
			Log.e(TAG, e.toString());
			return false;
		}	
	}

}
